home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / knowLocal.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  17KB  |  629 lines

  1. /*
  2.  * @(#)knowLocal.c    1.8  4/11/88
  3.  */
  4. #include "assert.h"
  5. #include "nodes.h"
  6. #include "map.h"
  7. #include "sequence.h"
  8. #include "trace.h"
  9. #include "semantics.h"
  10. #include "builtins.h"
  11. #include "primitives.h"
  12. #include "MyParser.h"
  13. #include "flags.h"
  14.  
  15. extern int nextLineNumber;
  16. static Map nodeToLocalStruct;
  17. extern Map manifestMap;
  18. static NodePtr noneNode;
  19.  
  20. #define LC_makeGlobal(parent) LC_TryToAddDependent(parent, noneNode)
  21.  
  22. static void LC_addDependent(parent, child)
  23. NodePtr parent, child;
  24. {
  25.   NodePtr childStruct;
  26.   NodePtr parentStruct;
  27.   parentStruct = (NodePtr) Map_Lookup(nodeToLocalStruct, (int)parent);
  28.   if ((int)parentStruct == NIL) {
  29.     parentStruct = Construct(P_KNOWLOCAL, 3, NN, NN, NN);
  30.     parentStruct->b.knowlocal.tag = parent->tag;
  31.     parentStruct->b.knowlocal.definingThing = parent;
  32.     Map_Insert(nodeToLocalStruct, (int)parent, (int)parentStruct);
  33.   }
  34.   childStruct = (NodePtr) Map_Lookup(nodeToLocalStruct, (int)child);
  35.   if ((int)childStruct == NIL) {
  36.     childStruct = Construct(P_KNOWLOCAL, 3, NN, NN, NN);
  37.     childStruct->b.knowlocal.tag = child->tag;
  38.     childStruct->b.knowlocal.definingThing = child;
  39.     Map_Insert(nodeToLocalStruct, (int)child, (int)childStruct);
  40.   }
  41.   SET_INSERT(parentStruct->b.knowlocal.dependsOn, childStruct);
  42. }
  43.  
  44. extern void resolveGlobal();
  45.  
  46. static void LC_TryToAddDependent(parent, child)
  47. NodePtr parent, child;
  48. {
  49.   Symbol st;
  50.   NodePtr at;
  51.  
  52.   if (parent->tag == T_NONE) return;
  53.   if (parent->tag == P_SYMDEF || parent->tag == P_SYMREF)
  54.     parent = (NodePtr) parent->b.symref.symbol;
  55.   if (child->tag == P_SYMDEF || child->tag == P_SYMREF)
  56.     child = (NodePtr) child->b.symref.symbol;
  57.   switch (parent->tag) {
  58.     case P_SYMBOL:
  59.       st = (Symbol) parent;
  60.       at = GETVALUE(st->value.ATinfo);
  61.       if (at->b.atlit.f.immutable) return;
  62.       if (st->isManifest) {
  63.     child = noneNode;
  64.       } else if (st->itsKind == ST_Result || st->itsKind == ST_Param) {
  65.     child = noneNode;
  66.       }
  67.       break;
  68.     case P_INVOC:
  69.       if (Map_Lookup(manifestMap, (int)parent) != NIL) {
  70.     child = noneNode;
  71.       }
  72.     default:
  73.       break;
  74.   }
  75.   switch (child->tag) {
  76.     case P_SYMBOL:
  77.       st = (Symbol) child;
  78.       if (st->itsKind == ST_Result || st->itsKind == ST_Param) child = noneNode;
  79.       LC_addDependent(parent, child);
  80.       break;
  81.     case P_GLOBALREF:
  82.       resolveGlobal(child, (ValuePtr)NULL);
  83.       assert(child->b.globalref.value != NN);
  84.       LC_addDependent(parent, child->b.globalref.value);
  85.       break;
  86.     case T_NONE:
  87.     case P_INVOC:
  88.     case P_VECTORLIT:
  89.     case P_BOOLLIT:
  90.     case P_CHARLIT:
  91.     case P_INTLIT:
  92.     case P_REALLIT:
  93.     case P_STRINGLIT:
  94.     case P_BUILTINLIT:
  95.     case P_SELFLIT:
  96.     case P_ATLIT:
  97.     case P_OBLIT:
  98.     case P_NTHRESULT:
  99.     case P_EXP:
  100.     case P_UNARYEXP:
  101.       LC_addDependent(parent, child);
  102.       break;
  103.     case P_SYMREF:
  104.       assert(FALSE);
  105.       break;
  106.     default:
  107.       LC_addDependent(parent, noneNode);
  108.       break;
  109.   }
  110. }
  111.  
  112. static Map nthMap;
  113.  
  114. static Boolean isSingleReferenceSymbol(), isACreation();
  115.  
  116. static NodePtr getNth(p, allowSelf)
  117. NodePtr p;
  118. Boolean allowSelf;
  119. {
  120.   register NodePtr nth, s = p;
  121.   if (s->tag != P_INVOC && s->tag != P_SYMREF) return(s);
  122.   if (s->tag == P_INVOC && isACreation(s) && allowSelf) return(s);
  123.   if (s->tag == P_INVOC) {
  124. #ifdef TRYINGTGETRESULTSLOCAL
  125.  
  126.     This is completely garbage!
  127.  
  128.     s = s->b.invoc.target;
  129.     if (s->tag != P_SYMREF || !isSingleReferenceSymbol(s)) {
  130.       nth = (NodePtr)Map_Lookup(nthMap, (int)s);
  131.       if (nth == (NodePtr)NIL) {
  132.     nextLineNumber = s->lineNumber;
  133.     nth = Construct(P_NTHRESULT, 0);
  134.     Map_Insert(nthMap, (int)s, (int)nth);
  135.     LC_makeGlobal(nth);
  136.       }
  137.       return(nth);
  138.     }
  139. #else
  140.     nth = (NodePtr)Map_Lookup(nthMap, (int)p);
  141.     if (nth == (NodePtr)NIL) {
  142.       nextLineNumber = p->lineNumber;
  143.       nth = Construct(P_NTHRESULT, 0);
  144.       Map_Insert(nthMap, (int)p, (int)nth);
  145.       LC_makeGlobal(nth);
  146.     }
  147.     return(nth);
  148. #endif
  149.   } else {
  150.     assert(s->tag == P_SYMREF);
  151.     nth = (NodePtr)Map_Lookup(nthMap, (int)s->b.symref.symbol);
  152.     if (nth == (NodePtr)NIL) {
  153.       nextLineNumber = s->lineNumber;
  154.       nth = Construct(P_NTHRESULT, 0);
  155.       Map_Insert(nthMap, (int)s->b.symref.symbol, (int)nth);
  156.       LC_TryToAddDependent(nth, (NodePtr)s->b.symref.symbol);
  157.     }
  158.     return(nth);
  159.   }
  160. }
  161.  
  162. extern Map nodeToStruct;
  163. extern NodePtr findObjectOperation(), OTLookup();
  164.  
  165. static NodePtr fetchCTInformation(p)
  166. NodePtr p;
  167. {
  168.   register NodePtr ct, thing;
  169.   register Symbol st;
  170.   if (p->tag == P_SYMREF || p->tag == P_SYMDEF) {
  171.     thing = (NodePtr) p->b.symdef.symbol;
  172.   } else if (p->tag == P_SYMBOL) {
  173.     thing = p;
  174.   } else {
  175.     thing = p;
  176.   }
  177.   ct = (NodePtr) Map_Lookup(nodeToStruct, (int) thing);
  178.   if (ct != (NodePtr)NIL) {
  179.     if (! ct->b.knowct.isOK) return(NULL);
  180.     ct = GETVALUE(ct->b.knowct.answer);
  181.     assert(ct != NULL);
  182.     assert(ct->tag == P_OBLIT);
  183.   } else {
  184.     ct = NN;
  185.     if (p->tag == P_SYMDEF || p->tag == P_SYMREF) {
  186.       st = p->b.symdef.symbol;
  187.       if (st->value.CTinfo != NN) ct = GETVALUE(st->value.CTinfo);
  188.     } else if (p->tag == P_SYMBOL) {
  189.       st = (Symbol) p;
  190.       if (st->value.CTinfo != NN) ct = GETVALUE(st->value.CTinfo);
  191.     }
  192.   }
  193.   return(ct);
  194. }
  195.  
  196. static Boolean isACreation(p)
  197. register NodePtr p;
  198. {
  199.   NodePtr ct, opdef;
  200.   assert(p->tag == P_INVOC);
  201.   ct = fetchCTInformation(p->b.invoc.target);
  202.   if (ct == NULL) return(FALSE);
  203.   assert(ct->tag == P_OBLIT);
  204.   opdef = findObjectOperation(ct, p->b.invoc.opname);
  205.   assert(opdef != NULL);
  206.   if (! opdef->b.opdef.isInlineable) return(FALSE);
  207.   if (opdef->b.opdef.body->b.block.stats->b.children[0]->tag != P_ASSIGNSTAT) return(FALSE);
  208.   return(opdef->b.opdef.body->b.block.stats->b.children[0]->b.assignstat.right->b.children[0]->tag == P_OBLIT);
  209. }
  210.  
  211. static Boolean isAConditionCreate(p)
  212. register NodePtr p;
  213. {
  214.   NodePtr ct;
  215.   assert(p->tag == P_INVOC);
  216.   ct = fetchCTInformation(p->b.invoc.target);
  217.   assert(ct != NULL);
  218.   assert(ct->tag == P_OBLIT);
  219.   return(ct->b.oblit.id == OIDOfBuiltin(B_IT, CONDITIONINDEX));
  220. }
  221.  
  222. extern NodePtr getCTInfo();
  223.  
  224. static Boolean isSingleReferenceSymbol(s)
  225. NodePtr s;
  226. {
  227.   register Symbol st;
  228.   register NodePtr ct;
  229.   if (s->tag != P_SYMREF) return(FALSE);
  230.   st = s->b.symref.symbol;
  231.   if (! s->b.symref.symbol->isSingleReference) return(FALSE);
  232.   if (s->b.symref.symbol->itsKind == ST_Param) return(FALSE);
  233.   if (s->b.symref.symbol->itsKind == ST_Result) return(FALSE);
  234.   ct = getCTInfo(st);
  235.   if (ct == NULL) return(FALSE);
  236.   assert(ct->tag == P_OBLIT);
  237.   if (! ct->b.oblit.f.doesNotDuplicateSelf) return(FALSE);
  238.   if (! ct->b.oblit.f.doesNotMoveArguments) return(FALSE);
  239.   if (! ct->b.oblit.f.doesNotMoveSelf) return(FALSE);
  240.   if (! ct->b.oblit.f.resultsDependOnlyOnArgs) return(FALSE);
  241.   return(TRUE);
  242. }
  243.  
  244. void buildKnowLocalGraph(p)
  245. register NodePtr p;
  246. {
  247.   register NodePtr q, right, left, nth, nthtrue;
  248.   register Symbol st;
  249.   Boolean wasACreation;
  250.  
  251.   if ((int)p <= 0x200) return;
  252.   switch (p->tag) {
  253.     case P_IMPORT:
  254.     case P_EXPORT:
  255.       if (p->b.export.path == NN) break;
  256.       Sequence_For(q, p->b.export.syms)
  257.     assert(q->tag == P_SYMDEF || q->tag == P_SYMREF);
  258.     LC_makeGlobal((NodePtr) q->b.symdef.symbol);
  259.       Sequence_Next
  260.       break;
  261.     case P_ASSIGNSTAT:
  262.       right = p->b.assignstat.right;
  263.       left = p->b.assignstat.left;
  264.       if (Sequence_Length(right) > 1) {
  265.     /* is a multiple assignment */
  266.     Sequence_For(q, left)
  267.       assert(q->tag == P_SYMREF);
  268.       nth = getNth(right->b.children[z__z], TRUE);
  269.       LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
  270.       LC_TryToAddDependent(nth, (NodePtr)q->b.symref.symbol);
  271.     Sequence_Next
  272.       } else {
  273.     Sequence_For(q, left)
  274.       assert(q->tag == P_SYMREF);
  275.       nth = getNth(right->b.children[0], TRUE);
  276.       LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
  277.       LC_TryToAddDependent(nth, (NodePtr)q->b.symref.symbol);
  278.     Sequence_Next
  279.       }
  280.       break;
  281.     case P_INVOC:
  282.       if ((q = (NodePtr) Map_Lookup(manifestMap, (int)p+2)) != (NodePtr) NIL) {
  283.     /* a manifest invocation */
  284.     LC_makeGlobal(p);
  285.     break;
  286.       }
  287. #ifdef JUNKKKKKKK
  288.       if (isACreation(p)) {
  289.     if (isAConditionCreate(p)) LC_makeGlobal(p);
  290.       } else {
  291.     LC_TryToAddDependent(p, getNth(p->b.invoc.target), TRUE);
  292.     nth = getNth(p, TRUE);
  293.     Sequence_For(q, p->b.invoc.args)
  294.       assert(q->tag == P_ARG);
  295.       q = q->b.arg.exp;
  296.       if (q->tag == P_SYMREF) {
  297.         LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
  298.       } else if (q->tag == P_INVOC) {
  299.         LC_TryToAddDependent(getNth(q, TRUE), nth);
  300.       } else {
  301.         LC_TryToAddDependent(q, nth);
  302.       }
  303.       LC_TryToAddDependent(nth, q);
  304.     Sequence_Next
  305.       }
  306. #else
  307.       wasACreation = isACreation(p);
  308.       if (wasACreation && isAConditionCreate(p)) {
  309.     LC_makeGlobal(p);
  310.       } else {
  311.     if (!wasACreation) {
  312.       LC_TryToAddDependent(p, getNth(p->b.invoc.target, TRUE));
  313.     }
  314.     nth = getNth(p, FALSE);
  315.     nthtrue = getNth(p, TRUE);
  316.     Sequence_For(q, p->b.invoc.args)
  317.       assert(q->tag == P_ARG);
  318.       q = q->b.arg.exp;
  319.       if (q->tag == P_SYMREF) {
  320.         LC_TryToAddDependent((NodePtr)q->b.symref.symbol, nth);
  321.       } else if (q->tag == P_INVOC) {
  322.         LC_TryToAddDependent(getNth(q, TRUE), nth);
  323.       } else {
  324.         LC_TryToAddDependent(q, nth);
  325.       }
  326.       if (!wasACreation) {
  327.         LC_TryToAddDependent(nthtrue, q);
  328.       }
  329.     Sequence_Next
  330.       }
  331. #endif
  332.       break;
  333.     case P_VECTORLIT:
  334.       Sequence_For(q, p->b.vectorlit.exp)
  335.     if (q->tag == P_SYMREF) {
  336.       LC_TryToAddDependent((NodePtr)q->b.symref.symbol, p);
  337.     } else if (q->tag == P_INVOC) {
  338.       LC_TryToAddDependent(getNth(q, TRUE), p);
  339.     } else {
  340.       LC_TryToAddDependent(q, p);
  341.     }
  342. #ifdef VECTORLITERALSDEPENDONARGS
  343.     LC_TryToAddDependent(p, q);
  344. #endif
  345.       Sequence_Next
  346.       break;
  347.     case P_CONSTDECL:
  348.       st = p->b.constdecl.sym->b.symdef.symbol;
  349.       if (st->isManifest) {
  350.     LC_makeGlobal((NodePtr)st);
  351.     break;
  352.       }
  353.     case P_VARDECL:
  354.       st = p->b.constdecl.sym->b.symdef.symbol;
  355.       if (p->b.constdecl.value != NN) {
  356.     nth = getNth(p->b.constdecl.value, TRUE);
  357.     LC_TryToAddDependent((NodePtr) st, nth);
  358.     LC_TryToAddDependent(nth, (NodePtr) st);
  359.       }
  360.       break;
  361.     case P_ATLIT:
  362.       break;
  363.     case P_OBLIT:
  364.       Sequence_For(q, p->b.oblit.setq)
  365.     if (q->b.setq.outer->tag == P_SYMREF) {
  366.       LC_makeGlobal((NodePtr)q->b.setq.outer->b.symref.symbol);
  367.     }
  368.     LC_makeGlobal((NodePtr)q->b.setq.inner->b.symdef.symbol);
  369.       Sequence_Next
  370.       LC_TryToAddDependent(p, p->b.oblit.name);
  371.       LC_TryToAddDependent(p->b.oblit.name, p);
  372.       break;
  373.     case P_VIEW:
  374.       if (p->b.view.exp->tag == P_INVOC) {
  375.     LC_makeGlobal(getNth(p->b.view.exp, TRUE));
  376.       } else {
  377.     LC_makeGlobal(p->b.view.exp);
  378.       }
  379.       break;
  380.     case P_RESTRICT:
  381.       LC_makeGlobal(p->b.restrict.exp);
  382.       break;
  383.     case P_MOVESTAT:
  384.     case P_FIXSTAT:
  385.     case P_REFIXSTAT:
  386.       LC_makeGlobal(p->b.movestat.exp);
  387.       break;
  388.     case P_UNFIXSTAT:
  389.       LC_makeGlobal(p->b.unfixstat.exp);
  390.       break;
  391.     default:
  392.       break;
  393.   }
  394.   Sequence_For(q, p)
  395.     if ((int)q > 0x200) buildKnowLocalGraph(q);
  396.   Sequence_Next
  397. }
  398.  
  399. void initializeKnowLocal()
  400. {
  401.   nodeToLocalStruct = Map_Create();
  402.   noneNode = Construct(T_NONE, 0);
  403.   nthMap = Map_Create();
  404. }
  405.  
  406. static char *thingName(t)
  407. NodePtr t;
  408. {
  409.   static char buffer[128];
  410.   if (t->b.knowlocal.tag == P_SYMBOL) sprintf(buffer, "Symbol %s (0x%08x)",
  411.     ST_SymbolName((Symbol)(t->b.knowlocal.definingThing)), t->b.knowlocal.definingThing);
  412.   else sprintf(buffer, "%s (0x%08x) on line %d", tagNames[(int)t->b.knowlocal.tag],
  413.     t->b.knowlocal.definingThing, t->b.knowlocal.definingThing->lineNumber);
  414.   return(buffer);
  415. }
  416.  
  417. extern void findAllLocals();
  418.  
  419. void displayKnowLocalGraph()
  420. {
  421.   NodePtr thing, theStruct, q;
  422.   IFTRACE(knowlocal, 5) {
  423.     Map_For(nodeToLocalStruct, thing, theStruct)
  424.       printf("struct 0x%08x %s", theStruct, thingName(theStruct));
  425.       if (theStruct->b.knowlocal.isDone) {
  426.     printf(" isDone");
  427.         printf("%s", theStruct->b.knowlocal.isOK ? " isOK" : " isNotOK");
  428.       }
  429.       printf(" depends on:\n");
  430.       Set_For(q, theStruct->b.knowlocal.dependsOn)
  431.     printf("\t\tstruct 0x%08x %s\n", q, thingName(q));
  432.       Set_Next
  433.     Map_Next
  434.   }
  435. }
  436.  
  437. #define CODEOIDOF(p) ((p)->b.oblit.codeOID)
  438.  
  439. void propagateLocalInfo(p)
  440. NodePtr p;
  441. {
  442.   NodePtr q, aSetMember, ct = NN, newct, dt;
  443.   Boolean isLocal = TRUE;
  444.   register Symbol st;
  445.  
  446.   if (p->tag != T_SEQUENCE) p = Construct(T_SEQUENCE, 1, p);
  447.  
  448.   Sequence_For(aSetMember, p)
  449.     dt = aSetMember->b.knowlocal.definingThing;
  450.     TRACE2(knowlocal, 3, "Looking at pre-reqs of 0x%08x %s", aSetMember,
  451.       thingName(aSetMember));    
  452.     Set_For(q, aSetMember->b.knowlocal.dependsOn)
  453.       TRACE2(knowlocal, 4, "Looking at 0x%08x %s", q, thingName(q));
  454.       assert(q->tag == P_KNOWLOCAL);
  455.       if (! q->b.knowlocal.isDone) continue; /* it is in this set */
  456.       if (!q->b.knowlocal.isOK) {
  457.     TRACE2(knowlocal, 4, "0x%08x %s not ok, give up", q, thingName(q));
  458.     isLocal = FALSE;
  459.       }
  460.     Set_Next
  461.     if (! isLocal) break;
  462.     assert(aSetMember->tag == P_KNOWLOCAL);
  463.     if (dt->tag == P_OBLIT || dt->tag == P_SYMBOL) {
  464.       newct = fetchCTInformation(dt);
  465.       if (newct == NN) {
  466.     TRACE2(knowlocal, 4, "0x%08x %s unknown ct, give up", aSetMember,
  467.       thingName(aSetMember));
  468.     isLocal = FALSE;
  469.       } else if (ct != NN && ct != newct) {
  470.     TRACE4(knowlocal, 4, "0x%08x %s different ct (0x%x != 0x%x), give up",
  471.       aSetMember, thingName(aSetMember), CODEOIDOF(newct), CODEOIDOF(ct));
  472.     isLocal = FALSE;
  473.       } else {
  474.     ct = newct;
  475.       }
  476.     }
  477.     if (! isLocal) break;
  478.     switch (aSetMember->b.knowlocal.tag) {
  479.       case T_NONE:
  480.     isLocal = FALSE;
  481.     break;
  482.       case P_INVOC:
  483.     if (Map_Lookup(manifestMap, (int)dt + 1) != NIL) {
  484.       isLocal = FALSE;
  485.       break;
  486.     } else {
  487.       isLocal = TRUE;
  488.     }
  489.     break;
  490.       case P_NTHRESULT:    /* worried about the result */
  491.     isLocal = TRUE;
  492.     break;
  493.       case P_UNARYEXP:
  494.       case P_EXP:
  495.       case P_BUILTINLIT:
  496.       case P_STRINGLIT:
  497.       case P_REALLIT:
  498.       case P_INTLIT:
  499.       case P_CHARLIT:
  500.       case P_BOOLLIT:
  501.     isLocal = FALSE;
  502.     break;
  503.       case P_VECTORLIT:
  504.     /* this could be local if its target is */
  505.     isLocal = TRUE;
  506.     break;
  507.       case P_SELFLIT:
  508.     assert(FALSE);
  509.     break;
  510.       case P_ATLIT:
  511.     isLocal = FALSE;
  512.     break;
  513.       case P_OBLIT:
  514.     isLocal = TRUE;
  515.     break;
  516.       case P_SYMBOL:
  517.     isLocal = TRUE;
  518.     break;
  519.       default:
  520.     isLocal = FALSE;
  521.     break;
  522.     }
  523.     if (!isLocal) break;
  524.   Sequence_Next
  525.   /* check that the ct is ok */
  526.   if (isLocal && ct != NN) {
  527.     if (! ct->b.oblit.f.doesNotDuplicateSelf) {
  528.       TRACE1(knowlocal, 4, "ct 0%x  duplicates self, give up", CODEOIDOF(ct));
  529.       isLocal = FALSE;
  530.     }
  531.     if (! ct->b.oblit.f.doesNotMoveSelf) {
  532.       TRACE1(knowlocal, 4, "ct 0%x  moves self, give up", CODEOIDOF(ct));
  533.       isLocal = FALSE;
  534.     }
  535.   }
  536.   Sequence_For(aSetMember, p)
  537.     aSetMember->b.knowlocal.isDone = TRUE;
  538.     aSetMember->b.knowlocal.isOK = isLocal;
  539.     aSetMember->b.knowlocal.answer = NULL;
  540.     TRACE3(knowlocal, 1, "Finalizing 0x%08x %s: %s", aSetMember,
  541.       thingName(aSetMember),
  542.       aSetMember->b.knowlocal.isOK ? "is local" : "is not local");
  543.     switch (aSetMember->b.knowlocal.tag) {
  544.       case P_SYMBOL:
  545.     st = (Symbol) aSetMember->b.knowlocal.definingThing;
  546.     st->isLocal = isLocal;
  547.     break;
  548.       case P_OBLIT:
  549.     aSetMember->b.knowlocal.definingThing->b.oblit.f.doLocalCreate = isLocal;
  550.     break;
  551.       case P_INVOC:
  552.     aSetMember->b.knowlocal.definingThing->b.invoc.isLocal = isLocal;
  553.     break;
  554.       case P_NTHRESULT:
  555.     break;
  556.       case P_VECTORLIT:
  557.     aSetMember->b.knowlocal.definingThing->b.vectorlit.f.doLocalCreate = isLocal;
  558.     break;
  559.       default:
  560.     break;
  561.     }
  562.   Sequence_Next
  563. }
  564.  
  565. static int count = 0;
  566. static NodePtr SCstack = NULL;
  567. static NodePtr SCComponent = NULL;
  568.  
  569. #define min(A, B) ((A) < (B) ? (A) : (B))
  570.  
  571. static void localSearchC(v)
  572. register NodePtr v;
  573. {
  574.   register NodePtr x;
  575.   NodePtr w;
  576.   v->b.knowlocal.marked = TRUE;
  577.   v->b.knowlocal.number = count++;
  578.   v->b.knowlocal.lowLink = v->b.knowlocal.number;
  579.   Sequence_Add(&SCstack, v);
  580.   v->b.knowlocal.onStack = TRUE;
  581.   Set_For(w, v->b.knowlocal.dependsOn)
  582.     if (! w->b.knowlocal.marked) {
  583.       localSearchC(w);
  584.       v->b.knowlocal.lowLink = min(v->b.knowlocal.lowLink, w->b.knowlocal.lowLink);
  585.     } else {
  586.       if (w->b.knowlocal.number < v->b.knowlocal.number && w->b.knowlocal.onStack) {
  587.     v->b.knowlocal.lowLink = min(w->b.knowlocal.number, v->b.knowlocal.lowLink);
  588.       }
  589.     }
  590.   Set_Next
  591.   if (v->b.knowlocal.lowLink == v->b.knowlocal.number) {
  592.     TRACE0(knowlocal, 1, "------");
  593.     Sequence_ReverseFor(x, SCstack)
  594.       SCstack->nChildren --;
  595.       assert(x->b.knowlocal.onStack);
  596.       x->b.knowlocal.onStack = FALSE;
  597.       if (SCComponent == NULL && x == v) {
  598.     /* this is the only element of the component */
  599.     SCComponent = x;
  600.       } else {
  601.     Sequence_Add(&SCComponent, x);
  602.       }
  603.       TRACE2(knowlocal, 2, "struct 0x%08x %s", x, thingName(x));
  604.       if (x == v) break;
  605.     Sequence_Next
  606.     propagateLocalInfo(SCComponent);
  607.     if (SCComponent->tag == T_SEQUENCE) {
  608.       free((char *)SCComponent);
  609.     }
  610.     SCComponent = NULL;
  611.   }
  612. }
  613.  
  614. static void FindAllLocals()
  615. {
  616.   NodePtr theThing, theStruct;
  617.   Map_For(nodeToLocalStruct, theThing, theStruct)
  618.     if (! theStruct->b.knowlocal.marked) localSearchC(theStruct);
  619.   Map_Next
  620. }
  621.  
  622. void doKnowLocals(p)
  623. NodePtr p;
  624. {
  625.   buildKnowLocalGraph(p);
  626.   displayKnowLocalGraph();
  627.   FindAllLocals();
  628. }
  629.